package com.common.boot.service.impl;

import com.common.boot.service.ICoordTransformService;
import org.springframework.stereotype.Component;

@Component
public class CoordTransformServiceImpl implements ICoordTransformService {
  /**
   * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02) 的转换 即 百度 转 谷歌、高德
   *
   * @param bdLng 经度
   * @param bdLat 纬度
   * @return the double [ ]
   */
  @Override
  public Double[] bd09ToGcj02(Double bdLng, Double bdLat) {
    bdLng = +bdLng;
    bdLat = +bdLat;
    Double x = bdLng - 0.0065;
    Double y = bdLat - 0.006;
    double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * XPI);
    double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * XPI);
    double gcLng = z * Math.cos(theta);
    double gcLat = z * Math.sin(theta);
    return new Double[] {gcLng, gcLat};
  }

  /**
   * 百度坐标系 (BD-09) 与 WGS-84的转换
   *
   * @param bdLng 经度
   * @param bdLat 纬度
   * @return the double [ ]
   */
  @Override
  public Double[] bd09ToWgs84(Double bdLng, Double bdLat) {
    Double[] gcDoubles = bd09ToGcj02(bdLng, bdLat);
    return gcj02ToWgs84(gcDoubles[0], gcDoubles[1]);
  }

  /**
   * 百度坐标系 (BD-09) 与 GZ2000的转换
   *
   * @param bdLng 经度
   * @param bdLat 纬度
   * @return the double [ ]
   */
  @Override
  public Double[] bd09ToGz2000(Double bdLng, Double bdLat) {
    Double[] doubles = bd09ToWgs84(bdLng, bdLat);
    return wgs84ToGz2000(doubles[0], doubles[1]);
  }

  /**
   * WGS-84 转 BD09
   *
   * @param wgLng 经度
   * @param wgLat 纬度
   * @return the double [ ]
   */
  @Override
  public Double[] wgs84ToBd09(Double wgLng, Double wgLat) {
    Double[] doubles = wgs84ToGcj02(wgLng, wgLat);
    return gcj02ToBd09(doubles[0], doubles[1]);
  }

  /**
   * WGS-84 转 GZ2000
   *
   * @param wgLng 经度
   * @param wgLat 纬度
   * @return the double [ ]
   */
  @Override
  public Double[] wgs84ToGz2000(Double wgLng, Double wgLat) {
    Double[] doubles = wgs84To2435(wgLng, wgLat);
    Double lng = doubles[0];
    Double lat = doubles[1];
    double x =
        T2345_TO_GZ2000_X
            + (1 + T2345_TO_GZ2000_M)
                * (Math.cos(T2345_TO_GZ2000_R) * lng - Math.sin(T2345_TO_GZ2000_R) * lat);
    double y =
        T2345_TO_GZ2000_Y
            + (1 + T2345_TO_GZ2000_M)
                * (Math.sin(T2345_TO_GZ2000_R) * lng + Math.cos(T2345_TO_GZ2000_R) * lat);
    return new Double[] {x, y};

    /*  CoordDTO coordDTO = null;
    try {
        coordDTO = gz2000ApiService.wsg84ToGz2000(wgLng, wgLat, tokens);
    } catch (Exception e) {
        e.printStackTrace();
        Assert.isTrue(false, e.getMessage());
    }

    return new Double[] {coordDTO.getX(), coordDTO.getY()};*/
  }

  /**
   * WGS-84 转 GCJ-02
   *
   * @param wgLng 经度
   * @param wgLat 纬度
   * @return the double [ ]
   */
  @Override
  public Double[] wgs84ToGcj02(Double wgLng, Double wgLat) {
    double lat = +wgLat;
    double lng = +wgLng;
    if (outOfChina(lng, lat)) {
      return new Double[] {lng, lat};
    } else {
      double dlat = transformLat(lng - 105.0, lat - 35.0);
      double dlng = transformLng(lng - 105.0, lat - 35.0);
      double radLat = lat / 180.0 * PI;
      double magic = Math.sin(radLat);
      magic = 1 - EE * magic * magic;
      double sqrtMagic = Math.sqrt(magic);
      dlat = (dlat * 180.0) / ((A * (1 - EE)) / (magic * sqrtMagic) * PI);
      dlng = (dlng * 180.0) / (A / sqrtMagic * Math.cos(radLat) * PI);
      double gcLat = lat + dlat;
      double gcLng = lng + dlng;
      return new Double[] {gcLng, gcLat};
    }
  }

  /**
   * 火星坐标系 (GCJ-02) 与 BD09 的转换
   *
   * @param gcLng 经度
   * @param gcLat 纬度
   * @return the double [ ]
   */
  @Override
  public Double[] gcj02ToBd09(Double gcLng, Double gcLat) {
    double lat = +gcLat;
    double lng = +gcLng;
    double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * XPI);
    double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * XPI);
    double bdLng = z * Math.cos(theta) + 0.0065;
    double bdLat = z * Math.sin(theta) + 0.006;
    return new Double[] {bdLng, bdLat};
  }

  /**
   * GCJ-02 转换为 WGS-84
   *
   * @param gcLng 经度
   * @param gcLat 纬度
   * @return the double [ ]
   */
  @Override
  public Double[] gcj02ToWgs84(Double gcLng, Double gcLat) {
    double lat = +gcLat;
    double lng = +gcLng;
    if (outOfChina(lng, lat)) {
      return new Double[] {lng, lat};
    } else {
      double dlat = transformLat(lng - 105.0, lat - 35.0);
      double dlng = transformLng(lng - 105.0, lat - 35.0);
      double radLat = lat / 180.0 * PI;
      double magic = Math.sin(radLat);
      magic = 1 - EE * magic * magic;
      double sqrtMagic = Math.sqrt(magic);
      dlat = (dlat * 180.0) / ((A * (1 - EE)) / (magic * sqrtMagic) * PI);
      dlng = (dlng * 180.0) / (A / sqrtMagic * Math.cos(radLat) * PI);
      double mgLat = lat + dlat;
      double mgLng = lng + dlng;
      return new Double[] {lng * 2 - mgLng, lat * 2 - mgLat};
    }
  }

  /**
   * GCJ-02 转换为 gz2000
   *
   * @param gcLng 经度
   * @param gcLat 纬度
   * @return the double [ ]
   */
  @Override
  public Double[] gcj02ToGz2000(Double gcLng, Double gcLat) {
    Double[] doubles = gcj02ToWgs84(gcLng, gcLat);
    return wgs84ToGz2000(doubles[0], doubles[1]);
  }

  /**
   * Gz2000 to Wgs84
   *
   * @param gzLng 经度
   * @param gzLat 纬度
   * @return the double [ ]
   */
  @Override
  public Double[] gz2000ToWgs84(Double gzLng, Double gzLat) {
    double x =
        GZ2000_TO_2435_X
            + (1 + GZ2000_TO_2435_M)
                * (Math.cos(GZ2000_TO_2435_R) * gzLng - Math.sin(GZ2000_TO_2435_R) * gzLat);
    double y =
        GZ2000_TO_2435_Y
            + (1 + GZ2000_TO_2435_M)
                * (Math.sin(GZ2000_TO_2435_R) * gzLng + Math.cos(GZ2000_TO_2435_R) * gzLat);
    return t2435ToWgs84(x, y);
    /* CoordDTO coordDTO = gz2000ApiService.gz2000ToWsg84(gzLng, gzLat, tokens);
    return new Double[]{coordDTO.getX(), coordDTO.getY()};*/
  }

  /**
   * Gz2000 to Wgs84
   *
   * @param gzLng 经度
   * @param gzLat 纬度
   * @return the double [ ]
   */
  @Override
  public Double[] gz2000ToBd09(Double gzLng, Double gzLat) {
    Double[] doubles = gz2000ToWgs84(gzLng, gzLat);
    return wgs84ToBd09(doubles[0], doubles[1]);
  }

  /**
   * Gz2000 to Gcj02
   *
   * @param gzLng 经度
   * @param gzLat 纬度
   * @return the double [ ]
   */
  @Override
  public Double[] gz2000ToGcj02(Double gzLng, Double gzLat) {
    Double[] doubles = gz2000ToWgs84(gzLng, gzLat);
    return wgs84ToGcj02(doubles[0], doubles[1]);
  }
}
